package cn.b504.qpcr.impls.data.manager;

import azure2java.qpcradapter.adapter.DataProcesserAdapter;
import cn.b504.qpcr.entity.data.MeltData;
import cn.b504.qpcr.entity.data.QuantificationData;
import cn.b504.qpcr.interfaces.data.manager.DataManagerDataBuilder;
import cn.b504.qpcr.utils.FileUtils;
import cn.b504.qpcr.utils.Utils;
import com.csvreader.CsvReader;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;

@Service
public class DataManagerDataBuilderImpl implements DataManagerDataBuilder {

  @Override
  @Async
  public Future<QuantificationData> buildPcr(DataProcesserAdapter processor, String filePath) {
    File csv = new File(filePath);
    // 生成 csv 文件。[警告：API 问题] 可能没生成 csv 成功 experimentalData2Csv 方法也返回 true
    if (!processor.experimentalData2Csv(filePath) || !csv.exists()) {
      FileUtils.deleteFile(csv);
      return new AsyncResult<>(new QuantificationData());
    }
    // 所有 step 的 96 个孔对应 channel 数据
    Map<String, List<List<List<Float>>>> mapAll = new HashMap<>();
    // 每一个 step 的 96 个孔对应 channel 数据
    Map<String, List<List<Float>>> mapStep = new HashMap<>();

    String currentChannel = "";
    CsvReader csvReader = null;
    int positionCount;
    try {
      // 通过文件绝对路径名、分隔符、字符集实例化 CsvReader 对象
      csvReader = new CsvReader(filePath, ',', StandardCharsets.UTF_8);
      csvReader.readHeaders();    // 读取首行
      positionCount = csvReader.getHeaderCount() - 2;
      while (csvReader.readRecord()) {    // 读取每一行
        String firstCell = csvReader.get(0);
        // 如果第一列是以“Step”开头，说明是一组的标志
        if (firstCell.startsWith("Step")) {
          // 捕捉最后一个字符，是 channel 值
          currentChannel = firstCell.substring(firstCell.length() - 1);
          if (!mapAll.containsKey(currentChannel)) {
            mapAll.put(currentChannel, new ArrayList<>());
          }
          List<List<Float>> step = Utils.init2DList(positionCount);
          mapStep.put(currentChannel, step);
          mapAll.get(currentChannel).add(step);
        } else {
          if (!mapStep.containsKey(currentChannel)) {
            mapStep.put(currentChannel, Utils.init2DList(positionCount));
          }
          for (int i = 1; i < csvReader.getColumnCount() - 1; i++) {
            //  TODO: 数据是否*1000
//            mapStep.get(currentChannel).get(i - 1).add(Float.parseFloat(csvReader.get(i)) * 1000); // 对取到的每一个结果：乘 1000
            mapStep.get(currentChannel).get(i - 1).add(Float.parseFloat(csvReader.get(i)));
          }
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
      return new AsyncResult<>(new QuantificationData());
    } finally {
      if (csvReader != null) {
        csvReader.close();  // 关闭 CsvReader 对象
      }
    }
    QuantificationData quantificationData = new QuantificationData();
    for (int i = 0; i < 6; i++) {
      List<List<Float>> lists = Utils.reduceOrDefault(mapAll.get(String.valueOf(i + 1)), Utils.init2DList(positionCount));
      quantificationData.setChannel(i, lists);
    }

    FileUtils.deleteFile(csv);
    return new AsyncResult<>(quantificationData);
  }

  @Override
  @Async
  public Future<MeltData> buildMelt(DataProcesserAdapter processor, String filePath) {
    File csv = new File(filePath);
    // 生成 csv 文件。[警告：API 问题] 可能没生成 csv 成功 meltingData2Csv 方法也返回 true
    if (!processor.meltingData2Csv(filePath) || !csv.exists()) {
      FileUtils.deleteFile(csv);
      return new AsyncResult<>(new MeltData());
    }
    List<List<Float>> data;
    float startTemp = 0F, secondTemp = 0F;
    CsvReader csvReader = null;
    try {
      // 通过文件绝对路径名、分隔符、字符集实例化 CsvReader 对象
      csvReader = new CsvReader(filePath, ',', StandardCharsets.UTF_8);
      csvReader.readHeaders();    // 读取首行
      data = Utils.init2DList(csvReader.getHeaderCount() - 2);
      int currentLine = 0;
      while (csvReader.readRecord()) {    // 读取每一行
        switch (currentLine++) {
          case 0:
            startTemp = Float.parseFloat(csvReader.get(0));
            break;
          case 1:
            secondTemp = Float.parseFloat(csvReader.get(0));
            break;
        }
        for (int i = 1; i < csvReader.getColumnCount() - 1; i++) {
          data.get(i - 1).add(Float.parseFloat(csvReader.get(i)) * 1000);   // 对取到的每一个结果：乘 1000
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
      return new AsyncResult<>(new MeltData());
    } finally {
      if (csvReader != null) {
        csvReader.close();  // 关闭 CsvReader 对象
      }
    }
    MeltData meltData = new MeltData();
    if (data.size() > 0) {
      meltData.setData(data);
      meltData.setStartTemperature(startTemp * 0.01F);
      meltData.setGradient((secondTemp - startTemp) * 0.01F);
    }

    FileUtils.deleteFile(csv);
    return new AsyncResult<>(meltData);
  }
}
